iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
自我挑戰組

chatGPT 帶你從零開始寫 websocket 連線遊戲系列 第 6

D6 websocket REQ/RES 模式的進化之旅: 打造一個 API-liked websocket

  • 分享至 

  • xImage
  •  

前言

websocket 的 REQ/RES 模式其實是不太健全的 API,今天我們會逐步調整實作,讓它越來越完整。同時昨天提到如何區分[RES1] 還是 [RES2] 的困擾也會在今天處理

websocket REQ/RES 模式 v1

async def handle_request(websocket, path):
    async for request in websocket:
        # 在這裡處理客戶端的請求
        response = process_request(request)

        # 將回應傳回客戶端
        await websocket.send(response)

def process_request(request):
    # 在這裡處理客戶端的請求,並返回回應
    return "這是回應: " + request

start_server = websockets.serve(handle_request, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

第一版,只能支援單支 API,所以我們需要再做一些擴充
需要稍微說明一下 async for request in websocket 這部分,它相當於連續不斷地呼叫 request = await websocket.recv()
這邊很像流水線,會有源源不絕地 request 要處理,而且這些 request 其實是不保證會按照時間順序送進來的
我們今天還沒有要處理不按順序的部分,關於這部分我們會再之後寫一篇文章討論

websocket REQ/RES 模式 v2

async def handle_request(websocket, path):
    if path == "/api1":
        async for request in websocket:
            response = process_api1_request(request)
            await websocket.send(response)
    elif path == "/api2":
        async for request in websocket:
            response = process_api2_request(request)
            await websocket.send(response)
    else:
        # 如果路徑不匹配任何已知的 API 端點,可以回應錯誤或採取其他操作
        await websocket.send("未知的 API 端點")

def process_api1_request(request):
    # 處理 API 1 的請求並返回回應
    return "這是 API 1 的回應: " + request

def process_api2_request(request):
    # 處理 API 2 的請求並返回回應
    return "這是 API 2 的回應: " + request

# start_server 和其餘部分同 v1

上面是經過擴充的第二版,支援一個以上的 API,聰明的看倌們應該會發現 if path == "/apixxx" 判斷的部分看起來跟路由有 87 % 像,開始越來越有 API 的長相了。

但是等等,雖然我可以區分 REQ1 和 REQ2,可是如果連續呼叫 REQ1 兩次,這樣透過 path == "/apixxx" 仍舊還是沒辦法區分阿
這時候我們就要再增加一個 request_id 變量作區別了

websocket REQ/RES 模式 v3

async def handle_request(websocket, path):
    async for request in websocket:
        try:
            # 解析收到的 JSON 請求
            request_data = json.loads(request)

            # 檢查請求是否包含請求 ID
            if 'request_id' in request_data:
                request_id = request_data['request_id']
                response = None

                # 根據路徑分派請求處理
                if path == "/api1":
                    response = process_api1_request(request_data)
                elif path == "/api2":
                    response = process_api2_request(request_data)
                else:
                    response = {'error': '未知的 API 端點'}

                # 將回應傳回客戶端,並使用請求 ID 進行識別
                response_data = {'request_id': request_id, 'response': response}
                await websocket.send(json.dumps(response_data))
            else:
                # 如果請求沒有請求 ID,則返回錯誤
                error_response = {'error': '請求缺少請求 ID'}
                await websocket.send(json.dumps(error_response))
        except json.JSONDecodeError:
            # 處理無效的 JSON 請求
            error_response = {'error': '無效的 JSON 請求'}
            await websocket.send(json.dumps(error_response))

# def process_api1_request(request) 以下部分同 v2

經過以上改動之後,我們就可以順利處理不同次呼叫的 REQ1 了

結語

今天我們實作了 websocket 的 REQ/RES 模式,透過逐步加入新的機制,讓它越來越接近完整的 API
明天我們會再繼續探討 SUB/PUB 模式的 websocket 實作,敬請期待!


上一篇
D5 建立定型化的 websocket 連線 - REQ/RES 和 SUB/PUB 模式
下一篇
D7 websocket SUB/PUB 模式
系列文
chatGPT 帶你從零開始寫 websocket 連線遊戲31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言